#pragma once
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "slStruct.h"
#include <cuda_runtime.h>
#include "vector"
#include "map"
#include <opencv2/highgui/highgui.hpp>
#include <Eigen/Core>

#ifndef slLog
#define slLog Log::getInstance()
#endif

#ifndef PI
#define PI 3.14159265359f
#endif

typedef std::vector<bool> BitCode;
typedef std::vector<BitCode> BitCodeList;
namespace SLCuda
{

    __device__ int getPhaseDevice(double sinPhase, double cosPhase);

    __global__ void decodePhaseShiftKernel(uchar *imagesCuda[], float *decodeImage, float *uncertainImage, int imagesNo, int length, float phaseShiftCutoff);

    __global__ void imageAdd(uchar *img1, uchar *img2, uchar *imgres, int length);

    __global__ void assginPointer(uchar **imagesCuda, uchar *image, int n);

    Mat decodePhaseShiftCuda(SL::Images &images, Size size, int n, float phaseShiftCutoff);

    __global__ void decodeGrayCodeKernel(uchar **imagesCuda, ushort *decodeImage, ushort *uncertainImage, int n, float cutoffPercentage);

    Mat decodeGrayCodeCuda(SL::Images &images, Size size, int n, float cutoffPercentage);

    BitCodeList generateGrayCode(int n);

    std::map<int, int> generateBitCodeMap(int grayCodeN);

    __global__ void decodeGrayCodeWithPhaseShiftKernel(ushort *grayDecodeImageDevice, ushort *grayUncertainImageDevice, ushort *unwrapGrayDecodeImageDevice, ushort *unwrapGrayUncertainImageDevice, float *phaseShiftDecodeImageDevice, float *phaseShiftUncertainImageDevice, int *bitCodeMapFirstDevice, int *bitCodeMapSecondDevice, int *unwrapBitCodeMapFirstDevice, int *unwrapBitCodeMapSecondDevice, float *decodeImage, int grayCodeN, int stripSize);

    Mat decodeGrayCodeWithPhaseShiftCuda(Mat grayDecodeImage, Mat unwrapGrayDecodeImage, Mat phaseShiftDecodeImage, Size imageSize, Size projectorSize, int grayCodeN);
}